import * as React from 'react';
import classNames from 'classnames';
import type TextArea from './TextArea';

export interface InputProps {
	children?: React.ReactNode;
	className?: string;
	placeholder?: string;
	defaultValue?: string;
	maxLength?: string;
	disabled?: boolean;
	size?: 'large' | 'middle' | 'small';
	addonBefore?: React.ReactNode;
	addonAfter?: React.ReactNode;
	prefix?: React.ReactNode;
	suffix?: React.ReactNode;
	allowClear?: boolean;
	value?: any;
	bordered?: boolean;

	onChange?: (e: React.MouseEvent<HTMLElement>) => void;
	onPressEnter?: (e: React.MouseEvent<HTMLElement>) => void;
	onKeyDown?: (e: React.MouseEvent<HTMLElement>) => void;
}

export interface InputState {
	value: any;
	focused: boolean;
	/** `value` from prev props */
	prevValue: any;
}

function resolveOnChange(target:any, e:any, onChange:any, targetVal?:string) {
	onChange && onChange(e);
}

function getOtherProps(props:any) {
	const {
		prefixCls,
		onPressEnter,
		addonBefore,
		addonAfter,
		prefix,
		suffix,
		allowClear,
		defaultValue,
		size,
		inputType,
		bordered,
		htmlSize,
		...otherProps
	} = props;
	
	return otherProps;
}

class Input extends React.Component<InputProps, InputState> {
	static TextArea: typeof TextArea;
	input!: HTMLInputElement;
	
	renderInput = () => {
		const {
			children,
			className,
			size,
			addonBefore,
			addonAfter,
			allowClear,
			bordered = true,
		} = this.props;
		const restProps = getOtherProps(this.props);
		let sizeCls = '';
		switch (size) {
			case 'large':
				sizeCls = 'lg';
				break;
			case 'small':
				sizeCls = 'sm';
				break;
			default:
			    break;
		}
		const prefixCls = 'bh-input';
		const classString = classNames(
			prefixCls,
			className,
			{
				[`${prefixCls}-${sizeCls}`]: sizeCls,
				[`${prefixCls}-borderless`]: !bordered,
			}
		);
		
		return <input {...restProps} 
		    className={classString} 
		    onChange={this.handleChange}
		    onKeyDown={this.handleKeyDown}
		    ref={this.saveInput}
		/>
	}
	saveInput = (input: HTMLInputElement) => {
		this.input = input;
	};
	handleKeyDown = (e: any) => {
		const { onPressEnter, onKeyDown } = this.props;
		if (onPressEnter && e.keyCode === 13) {
			onPressEnter(e);
		}
		onKeyDown?.(e);
	}
	handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		this.setValue(e.target.value);
		resolveOnChange(this.input, e, this.props.onChange);
	}
	setValue(value: string, callback?: () => void) {
		if (this.props.value === undefined) {
			this.setState({ value }, callback);
		} else {
			callback?.();
		}
	}
	renderComponent = () => {
		const prefixCls = 'bh-input';
		const { 
			addonBefore,
			addonAfter,
			prefix,
			suffix,
			//disabled,
			//readOnly,
			value,
			allowClear,
		} = this.props;
		const hasWrap = !!addonBefore || !!addonAfter || !!prefix || !!suffix;
		const needClear = true;//value;
		
		const classString1 = classNames(
			`${prefixCls}-suffix`,
			{
				[`${prefixCls}-clear-icon-hidden`]: !needClear,
			}
		);
		const renderFix = () => {
			if(!!prefix || !!suffix || !!allowClear) {
				return (<span className="bh-input-affix-wrapper">
					{prefix && <span className="bh-input-prefix">{prefix}</span>}
					{this.renderInput()}
					{suffix && <span className="bh-input-suffix">{suffix}</span>}
					{allowClear && <span className={classString1}>
					    <i className="bh-input-clear-icon bh-icon bh-icon-close"></i>
					</span>}
				</span>)
			}else {
				return (<>{this.renderInput()}</>)
			}
		};

		if(hasWrap) {
			return (<span className="bh-input-group-wrapper">
				<span className="bh-input-wrapper bh-input-group">
				    {addonBefore && <span className="bh-input-group-addon">{addonBefore}</span>}
				    {renderFix()}
				    {addonAfter && <span className="bh-input-group-addon">{addonAfter}</span>}
				</span>
			</span>);
		}else if(allowClear) {
			return (<>{renderFix()}</>);
		}
		return (this.renderInput());
	}
	render () {
		return <>{this.renderComponent()}</>
	}
};

export default Input;